home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cocktail
/
lalr.lha
/
lalr
/
src
/
Reduce.mi
< prev
Wrap
Text File
|
1992-08-18
|
7KB
|
326 lines
(* check if the grammar is reduced *)
(* $Id: Reduce.mi,v 2.2 1992/08/07 15:22:49 grosch rel $ *)
(* $Log: Reduce.mi,v $
* Revision 2.2 1992/08/07 15:22:49 grosch
* allow several scanner and parsers; extend module Errors
*
* Revision 2.1 1991/11/21 14:53:14 grosch
* new version of RCS on SPARC
*
* Revision 2.0 91/03/08 18:31:50 grosch
* turned tables into initialized arrays (in C)
* moved mapping tokens -> strings from Errors to Parser
* changed interface for source position
*
* Revision 1.1 90/06/12 16:54:34 grosch
* renamed main program to lalr, added { } for actions, layout improvements
*
* Revision 1.0 88/10/04 14:36:38 vielsack
* Initial revision
*
*)
IMPLEMENTATION MODULE Reduce;
FROM SYSTEM IMPORT
ADR;
FROM Errors IMPORT
eWarning, eError, eIdent, ErrorMessage, ErrorMessageI;
FROM Sets IMPORT
tSet,
MakeSet, ReleaseSet,
Include, Exclude,
Extract,
IsElement, IsEmpty,
ForallDo;
FROM Automaton IMPORT
tIndex,
tStateIndex,
tProdIndex,
tItemIndex,
StartSymbol,
tProduction,
ProdList,
ProdArrayPtr;
FROM TokenTab IMPORT
MINTerm, MAXTerm,
MINNonTerm, MAXNonTerm,
Vocabulary,
Terminal, NonTerminal,
PosType, GetTokenPos,
TokenError, TokenType,
GetTokenType, TokenToSymbol;
FROM Idents IMPORT
tIdent;
CONST
eNotReach = 47;
eNoProd = 46;
eNotTerm = 45;
PROCEDURE TestReduced;
(* prueft ob die im Modul Automaton bekannte Grammatik
reduziert ist. Falls nein wird das Programm mittels einer
Fehlermeldung abgebrochen *)
VAR
ok, okreach, okterm : BOOLEAN;
reached : tSet; (* erreichbare Symbole *)
BEGIN
MakeSet (reached,MAXNonTerm);
okreach := TestReach (reached);
okterm := TestTerm (reached);
ok := (* okreach AND *) okterm; (* kein genereller Abbruch *)
Reduced := ok;
ReleaseSet (reached);
END TestReduced;
PROCEDURE TestReach (reached: tSet) : BOOLEAN;
(* Pruefe ob alle Vokabularzeichen erreichbar sind *)
VAR
reach : BOOLEAN; (* Funktionsergebniss *)
t : Terminal;
nt : NonTerminal;
todo : tSet; (* noch zu bearbeiten *)
done : tSet; (* bereits bearbeitet *)
u, i : tIndex;
pn : tProdIndex;
prod : tProduction;
ri,voc : Vocabulary;
error : TokenError;
sym : tIdent; (* zur Fehlerausgabe *)
pos : PosType;
BEGIN
MakeSet (todo,MAXNonTerm);
MakeSet (done,MAXNonTerm);
(* Startsymbol ist zu bearbeiten *)
Include (todo,StartSymbol);
Include (reached,StartSymbol);
(* Terminale sind nicht mehr zu bearbeiten *)
FOR t := MINTerm TO MAXTerm DO
IF GetTokenType (t) = Term THEN
Include (done,t);
END;
END;
REPEAT
(* waehle ein Nichtterminal zur Bearbeitung aus *)
nt := Extract (todo);
Include (done, nt);
WITH ProdList[nt] DO
u := Used;
(* fuer alle Produktionen mit linker Seite nt *)
FOR pn := 1 TO u DO
(* waehle aktuelle Produktion aus *)
prod := ADR(ProdArrayPtr^[Array^[pn].Index]);
WITH prod^ DO
(* alle Vocabularzeichen auf der rechten Seite werden *)
(* hiermit erreichbar *)
FOR i := 1 TO Len DO
ri := Right [i];
Include (reached, ri);
(* noch nicht erledigte Vokabularzeichen die rechts *)
(* auftreten sind zu bearbeiten *)
IF NOT IsElement (ri, done) THEN
Include (todo, ri);
END;
END;
END;
END;
END;
UNTIL IsEmpty (todo);
reach := TRUE;
(* pruefe ob alle Vocabularzeichen erreichbar sind *)
(* gebe ggf. eine Fehlermeldung aus *)
FOR voc := MINTerm TO MAXTerm DO
IF (GetTokenType (voc) <> None) AND
NOT IsElement (voc, reached) THEN
GetTokenPos (voc,pos);
sym := TokenToSymbol (voc,error);
ErrorMessageI (eNotReach, eWarning, pos,eIdent, ADR (sym));
END;
END;
FOR voc := MINNonTerm TO MAXNonTerm DO
IF (GetTokenType (voc) <> None) AND
NOT IsElement (voc, reached) THEN
GetTokenPos (voc,pos);
sym := TokenToSymbol (voc,error);
ErrorMessageI (eNotReach, eWarning, pos, eIdent, ADR (sym));
(* nichtereichbare Nichtterminal sind toetlich *)
reach := FALSE;
END;
END;
ReleaseSet (todo);
ReleaseSet (done);
RETURN reach;
END TestReach;
PROCEDURE TestTerm (reached: tSet) : BOOLEAN;
(* Pruefe ob alle Nichtterminale terminalisierbar sind *)
VAR
todo : tSet; (* noch zu ueberpruefende Nichterminale *)
done : tSet; (* als terminalisierbar erkannte Vokabularzeichen *)
success : BOOLEAN; (* hatte der letzte Schritt erfolg *)
t : Terminal;
nt : NonTerminal;
term : BOOLEAN;
error : TokenError;
sym : tIdent;
pos : PosType;
kind : CARDINAL;
PROCEDURE IsYetTerm (nt : CARDINAL);
VAR
u, i : tIndex;
pn : tProdIndex;
prod : tProduction;
ri : Vocabulary;
t : Terminal;
localsuccess : BOOLEAN;
BEGIN
WITH ProdList[nt] DO
u := Used;
(* Betrachte alle Produktionen mit linker Seite nt *)
localsuccess := FALSE;
pn := 1;
WHILE (pn <= u) AND NOT localsuccess DO
(* Auswahl der einzelnen Produktion *)
prod := ADR(ProdArrayPtr^[Array^[pn].Index]);
WITH prod^ DO
(* Pruefe ob rechte Seite in todo* liegt *)
localsuccess := TRUE;
i := 1;
WHILE (i <= Len) AND localsuccess DO
ri := Right [i];
localsuccess := IsElement (ri,done);
INC (i);
END;
END;
INC (pn);
END;
END;
IF localsuccess THEN
Include (done, nt);
Exclude (todo, nt);
success := TRUE
END;
END IsYetTerm;
BEGIN
MakeSet (todo,MAXNonTerm);
MakeSet (done,MAXNonTerm);
(* todo = Menge aller Nichtterminale *)
FOR nt := MINNonTerm TO MAXNonTerm DO
IF GetTokenType (nt) = NonTerm THEN
Include (todo,nt);
END;
END;
(* done := Menge alle Terminale *)
FOR t := MINTerm TO MAXTerm DO
IF GetTokenType (t) = Term THEN
Include (done,t);
END;
END;
REPEAT
success := FALSE;
(* Pruefe ob jetzt ein weiteres *)
(* Nichtterminal terminalisierbar ist *)
FOR nt := MINNonTerm TO MAXNonTerm DO
IF IsElement (nt, todo) THEN
IsYetTerm (nt);
END;
END;
UNTIL NOT success; (* solange bis sich nichts aendert *)
term := TRUE;
IF NOT IsEmpty (todo) THEN
REPEAT
nt := Extract (todo);
(* Ein ereichbares Nichtterminal, das nicht terminalisiserbar
ist, fuehrt zum Abbruch *)
IF IsElement (nt, reached) THEN
term := FALSE;
kind := eError;
ELSE
kind := eWarning;
END;
GetTokenPos (nt,pos);
sym := TokenToSymbol (nt,error);
IF ProdList[nt].Used = 0 THEN
ErrorMessageI (eNoProd, kind, pos, eIdent, ADR (sym));
ELSE
ErrorMessageI (eNotTerm, kind, pos, eIdent, ADR (sym));
END;
UNTIL IsEmpty (todo);
END;
ReleaseSet (todo);
ReleaseSet (done);
RETURN term;
END TestTerm;
END Reduce.